/* vim:ft=objc:
 * $Id: MacBiff.m 139 2005-05-21 17:35:44Z bmoore $
 *
 * Copyright (c) 2004, 2005  Branden J. Moore.
 *
 * This file is part of MacBiff, and is free software; you can redistribute
 * it and/or modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * MacBiff is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with MacBiff; if not, write to the Free Software Foundation, Inc., 59
 * Temple Place, Suite 330, Boston, MA  02111-1307 USA.
 *
 */

#include <string.h>
#include <signal.h>

#import "MacBiff.h"
#import "AccountInfo.h"
#import "ConfigController.h"
#import <MacBiffPlugIn/plugins.h>
#import <MacBiffPlugIn/PreferencesController.h>

#include "version.h"
#include "debug.h"
#if 0
#  define EBUG 1
#endif


void loadAllBundles(void);

volatile sig_atomic_t user_pressed_stop = 0;
MacBiff *macbiffController = Nil;
NSMenu* gMainMenu = Nil;
NSLock* gMenuLock = Nil;
extern NSMutableDictionary *accountBundles;

/* Signal Handlers */
static void sigUSR1( int sig )
{
	/* Send SIGURS1 to make MacBiff check for new mail *now* */
	dprintf("Received SIGUSR1\n");
	if ( macbiffController ) {
		[macbiffController performSelectorOnMainThread: @selector(refresh:)
						    withObject: macbiffController
						 waitUntilDone: NO];
	}
}


static void sigUSR2( int sig )
{
	/* Send SIGUSR2 to halt a check */
	dprintf("Received SIGUSR2\n");
}


@implementation MacBiff

- (void) loadAccounts
{
	NSArray *list = [prefs accountList];
	NSEnumerator *acctEnum = [list objectEnumerator];
	NSString *acctName = Nil;

	dprintf("Found %d accounts to load.\n", [list count]);
	while ( (acctName = [acctEnum nextObject]) ) {
		Class acctClass;
		actWinCloseAfterCheck = NO;
		Account *account = Nil;
		AccountInfo *info = Nil;
		NSString *type = Nil;

		dprintf("Loading Account: '%s'\n", [acctName cString]);
		type = [[prefs account: acctName] objectForKey: @"Type"];
		dprintf("...  Of Type:    '%s'\n", [type cString]);
		acctClass = [[accountBundles objectForKey: type]
			principalClass];
		account = [[acctClass alloc] initWithName: acctName];
		if ( !account ) {
			alert("Account failed to init\n");
			continue;
		}

		info = [[AccountInfo alloc] initWithAccount: account
				andMenu: mainMenu andLock: menuLock];
		if ( !info ) {
			alert("AccountInfo failed to initialize\n");
		} else {
			[info activate: Nil];
			dprintf("Account activated.\n");
			[accounts addObject: info];
			[info release];
		}
		[account release];
	}

	[detachControl setAccountList: accounts];
}


-(id) init
{
	struct sigaction usr1act, usr2act;
	memset(&usr1act, 0, sizeof(struct sigaction));
	memset(&usr2act, 0, sizeof(struct sigaction));
	sigemptyset(&(usr1act.sa_mask));
	sigemptyset(&(usr2act.sa_mask));

	usr1act.sa_handler = sigUSR1;
	usr1act.sa_flags = SA_RESTART;
	sigaction(SIGUSR1, &usr1act, NULL);

	usr2act.sa_handler = sigUSR2;
	sigaction(SIGUSR2, &usr2act, NULL);

	if ( ( self = [super init] ) != Nil ) {

		macbiffController = self;

		/* Load up plugins */
		loadAllBundles();
	}

	return self;
}


-(void) dealloc
{
	if ( systemBar ) [systemBar release];
	if ( checkStatusMenuItem ) [checkStatusMenuItem release];
	if ( mainMenu ) [mainMenu release];

	if ( prefs ) [prefs release];

	if ( accounts ) {
		NSEnumerator *acctEnum = [accounts objectEnumerator];
		AccountInfo *acct;
		while ( (acct = [acctEnum nextObject]) ) {
			[acct deactivate: Nil];
		}
		[accounts release];
	}

	[super dealloc];
}


- (void)awakeFromNib
{
	id <NSMenuItem> menuItem = Nil;

	gMenuLock = menuLock = [[NSLock alloc] init];
	gMainMenu = mainMenu = [[NSMenu alloc] initWithTitle: @"MacBiff"];

	checkStatusMenuItem =
		[[NSMenuItem alloc] initWithTitle: CHECK_NOW_STR
			action: @selector(menuCheckNow:)
			keyEquivalent: @""];
	[checkStatusMenuItem setTarget: self];
	[checkStatusMenuItem retain];

	[mainMenu addItem: checkStatusMenuItem];

	menuItem = [mainMenu addItemWithTitle: CONFIGURE_STR
		action: @selector(menuConfigure:)
		keyEquivalent: @""];
	[menuItem setTarget: self];

	menuItem = [mainMenu addItemWithTitle: DETACH_STR
		action: @selector(menuDetach:)
		keyEquivalent: @""];
	[menuItem setTarget: self];

	menuItem = [mainMenu addItemWithTitle: SHOW_ACTIVITY_STR
		action: @selector(menuShowActivity:)
		keyEquivalent: @""];
	[menuItem setTarget: self];

	menuItem = [mainMenu addItemWithTitle: LAUNCH_MAIL_STR
		action: @selector(menuLaunchMail:)
		keyEquivalent: @""];
	[menuItem setTarget: self];

	menuItem = [mainMenu addItemWithTitle: ABOUT_STR
		action: @selector(menuAbout:)
		keyEquivalent: @""];
	[menuItem setTarget: self];

	menuItem = [mainMenu addItemWithTitle: QUIT_STR
		action: @selector(menuQuit:)
		keyEquivalent: @""];
	[menuItem setTarget: self];

	systemBar = [[NSStatusBar systemStatusBar]
		statusItemWithLength: 65.0];
	[systemBar retain];
	[systemBar setAlternateImage: [NSImage imageNamed: @"highlight.png"]];

	[systemBar setHighlightMode: YES];
	[systemBar setMenu: mainMenu];
	[self setBarTitle: Nil];


	accounts = [[NSMutableArray alloc] initWithCapacity: 5];
	[self loadAccounts];
	/* Share Account List */
	[configController setAccountList: accounts];

	dprintf("*!*!*!*!*!*! MacBiff Finished Loading *!*!*!*!*!*!\n");
}


- (void)applicationDidFinishLaunching
{
	NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
	[[workspace notificationCenter] addObserver: self
					   selector: @selector(menuCheckNow:)
					       name: NSWorkspaceDidWakeNotification
					     object: workspace];

}

/********* End Initialization / De-initialization code **********/



- (IBAction)goToMacBiff: (id)sender
{
	[[NSWorkspace sharedWorkspace]
		openURL: [NSURL URLWithString:
			@"http://www.forkit.org/macbiff/macbiff.php"]];
}


- (void) setBarTitle: (id) obj
{
	NSDictionary *attrs = Nil;
	NSAttributedString *attrString = Nil;
	NSColor *color = Nil;
	char border1, border2;
	NSString *myString = Nil;
	uint32_t unread, total;

	dprintf("Configuring SystemBar Title\n");

	AccountInfo *acct = Nil;
	NSEnumerator *acctEnum = [accounts objectEnumerator];
	total = 0;
	unread = 0;
	while ( (acct = [acctEnum nextObject]) ) {
		if ( [acct enabled] ) {
			total += [[acct account] total];
			unread += [[acct account] unread];
		}
	}

	if ( actWinCloseAfterCheck && !checkingNow ) {
		[actWin close];
		actWinCloseAfterCheck = NO;
	}

	if ( [[[prefs display] objectForKey: @"Show Text"] boolValue] ) {
		border1 = Nil; //(checkingNow) ? '{' : Nil;
		border2 = Nil; //(checkingNow) ? '}' : Nil;

		if ( [[[prefs display] objectForKey: @"Show Total"] boolValue] ) {
			myString = [NSString stringWithFormat: @"%c%u/%u%c",
				 border1, unread, total, border2];
		} else {
			myString = [NSString stringWithFormat: @"%c%u%c",
				 border1, unread, border2];
		}

		color = (unread) ? [NSColor blackColor] : [NSColor blackColor];
		attrs = [NSDictionary dictionaryWithObjectsAndKeys:
			color, NSForegroundColorAttributeName,
			[NSFont menuBarFontOfSize: 14], NSFontAttributeName,
			Nil];
		attrString = [[NSAttributedString alloc]
				initWithString: myString
				attributes: attrs];
		[systemBar setAttributedTitle: attrString];
		[attrString release];
	} else {
		[systemBar setTitle: nil];
	}

	if ( [[[prefs display] objectForKey: @"Show Icon"] boolValue] ) {
		if ( unread ) {
			if ( checkingNow ) {
				[systemBar setImage: [NSImage imageNamed: @"unreadcheck.png"]];
			} else {
				[systemBar setImage: [NSImage imageNamed: @"unread.png"]];			
			}
		} else {
			if ( checkingNow ) {
				[systemBar setImage: [NSImage imageNamed: @"nonech.png"]];
			} else {
				[systemBar setImage: [NSImage imageNamed: @"none.png"]];
			}		
		}
	}

	[systemBar setLength: NSVariableStatusItemLength];

	/* Easy a place as elsewhere to keep it up to date */
	[detachControl update: Nil];
	if ( !checkingNow ) {
		/* Cancel the stop, if all have stopped now */
		user_pressed_stop = 0;
	}
}


- (void) noOp: (id)sender
{
}


- (void) menuCheckNow: (id)sender
{
	NSEnumerator *acctEnum = [accounts objectEnumerator];
	AccountInfo *acct;
	if ( [[[prefs misc] objectForKey: @"Show Activity On Check"]
			boolValue] && ![actWin isVisible] ) {
		actWinCloseAfterCheck = YES;
		[self menuShowActivity: sender];
	}
	while ( (acct = [acctEnum nextObject]) ) {
		[acct checkNow: Nil];
	}

	/* if we implement a stop check here, need to set user_pressed_stop */
}


- (void) menuConfigure: (id)sender
{
	[configController configure: self];
}


- (void) menuDetach: (id)sender
{
	[detachControl detach];
}


- (void) menuShowActivity: (id)sender
{
	[actWin makeKeyAndOrderFront: self];
	[NSApp activateIgnoringOtherApps: YES];
}


- (void) menuLaunchMail: (id)sender
{
	[[NSWorkspace sharedWorkspace] launchApplication:
		[[prefs misc] objectForKey: @"Mail App"]];
}


- (void)menuAbout: (id)sender
{
	[aboutVersionTextField setStringValue:
		[NSString stringWithFormat: @"MacBiff Version %s",
			VERSION]];
	[aboutRevTextField setStringValue:
		[NSString stringWithCString: SVN_REV]];

	[aboutWin makeKeyAndOrderFront: self];
	[NSApp activateIgnoringOtherApps: YES];
}


- (IBAction)closeAboutWin: (id)sender
{
	[aboutWin close];
}


- (void) menuQuit: (id)sender
{
	[NSApp terminate: self];
}


@end
